﻿//===============================================================================
// Microsoft patterns & practices Enterprise Library Contribution
// Mapping Application Block
//===============================================================================

using System;
using System.Data;
using System.Reflection;
using System.Configuration;
using System.Collections.Generic;
using System.Globalization;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using EntLibContrib.Mapping.Instrumentation;
using EntLibContrib.Mapping.Configuration;
using EntLibContrib.Mapping.Properties;

namespace EntLibContrib.Mapping.Mappers
{
	/// <summary>
	/// A Mapper provides a conversion between a single domain object and a data transfer object.
	/// </summary>
	[ConfigurationElementType(typeof(BasicMapperData))]
	public class BasicMapper : MapperBase
	{
		#region Constants
		private MapperType mapperType = MapperType.Basic;
		#endregion

		#region Fields
		private string domainObjectTypeName;
		#endregion

		#region Properties
		/// <summary>
		/// Gets the type of the mapper.
		/// </summary>
		/// <value>The type of the mapper.</value>
		public override MapperType MapperType
		{
			get { return mapperType; }
		}

		/// <summary>
		/// Gets the domain object type name.
		/// </summary>
		/// <value>The domain object type name.</value>
		public string DomainObjectTypeName
		{
			get { return domainObjectTypeName; }
		}
		#endregion

		#region Construction
		/// <summary>
		/// Initializes a new default instance of the <see cref="BasicMapper"/> class.
		/// </summary>
		/// <param name="name">The mapper name.</param>
		/// <param name="tableName">The data transfer object table name.</param>
		/// <param name="domainObjectTypeName">The domain object type name.</param>
		/// <param name="maps">The maps.</param>
		/// <param name="instrumentationProvider">The instrumentation provider.</param>
		public BasicMapper(string name,
											string tableName,
											string domainObjectTypeName,
											MapDictionary maps, 
											MappingInstrumentationProvider instrumentationProvider)
			: base(name, tableName, maps, instrumentationProvider)
		{
			if (string.IsNullOrEmpty(domainObjectTypeName))
				throw new ArgumentNullException("domainObjectTypeName");

			this.domainObjectTypeName = domainObjectTypeName;
		}
		#endregion

		#region Protected Methods
		/// <summary>
		/// Creates a new populated domain object.
		/// </summary>
		/// <typeparam name="T">The domain object type</typeparam>
		/// <param name="dataTransferTableRow">The data transfer table row containing the domain object property values.</param>
		/// <returns>a populated domain object</returns>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter")]
		protected override T CreateDomainObject<T>(DataRow dataTransferTableRow)
		{
			// get the type information
			Type domainObjectType = Type.GetType(domainObjectTypeName);
			// attempt to load the assembly containing the type if not already loaded
			Assembly domainAssembly = Assembly.Load(domainObjectType.Assembly.FullName);
			// attempt to create an instance of the domain object type
			T domainObject = (T)domainAssembly.CreateInstance(domainObjectType.FullName, true);
			// fill the domain object properties
			FillDomainObject<T>(domainObject, dataTransferTableRow);
			// return the populated object
			return domainObject;
		}
		#endregion
	}
}
